package com.zc.angelica.service.impl;

import cn.hutool.core.lang.tree.Tree;
import cn.hutool.crypto.digest.BCrypt;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zc.angelica.entity.*;
import com.zc.angelica.entity.request.Register;
import com.zc.angelica.entity.response.AccountResponse;
import com.zc.angelica.mapper.AccountMapper;
import com.zc.angelica.service.*;
import com.zc.angelica.utils.SecurityUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

import static java.util.Calendar.*;

/**
 * (Account)表服务实现类
 *
 * @author makejava
 * @since 2022-04-04 12:00:10
 */
@Service
public class AccountServiceImpl extends ServiceImpl<AccountMapper, Account> implements AccountService {


    @Value("${validateCode.enabled}")
    private Boolean enabledVerifyCode;

    @Value("${jwt.lasting-code}")
    private String lastingCode;

    @Autowired
    private AccountClientService accountClientService;

    @Autowired
    private ClientInfoService clientInfoService;

    @Autowired
    private UserInfoService userInfoService;

    @Autowired
    private RoleMenuInfoService roleMenuInfoService;

    @Autowired
    private AccountPlatformInfoService accountPlatformInfoService;

    @Override
    public ResponseData register(Register register, HttpServletRequest request) {
        if (register == null) {
            return ResponseData.error("请求不能为空！");
        }
        String validateCode = (String) request.getSession().getAttribute("validateCode");
        String clientCode = register.getClientCode();
        if (clientCode == null || clientCode.equals("")) {
            clientCode = request.getHeader(lastingCode);
        }

        if (enabledVerifyCode) {
            if (register.getVerifiCode() == null || validateCode == null) {
                return ResponseData.error("验证码不能为空！");
            }
            if (!validateCode.equals(register.getVerifiCode())) {
                return ResponseData.error("验证码输入错误！");
            }
        }
        if (register.getPassword() == null || register.getConfirmPassword() == null) {
            return ResponseData.error("密码不能为空！");
        }

        if (!register.getPassword().equals(register.getConfirmPassword())) {
            return ResponseData.error("输入的俩次密码不一致！");
        }
        if (register.getUsername() == null) {
            return ResponseData.error("用户名不能为空！");
        }

        QueryWrapper<Account> accountWrapper = new QueryWrapper<>();
        accountWrapper.eq("username", register.getUsername());
        List<Account> account = this.baseMapper.selectList(accountWrapper);
        if (account != null && account.size() > 0) {
            return ResponseData.error("用户名已经存在！");
        }
        if (clientCode == null || clientCode.equals("")) {
            return ResponseData.error("客户端code不能为空！");
        }
        Account accountInfo = new Account();
        accountInfo.setUsername(register.getUsername());
        accountInfo.setPassword(BCrypt.hashpw(register.getPassword()));
        accountInfo.setLockedlag(1);
        accountInfo.setIsEnabled(1);
        accountInfo.setIsExpired(3);
        int insert = this.baseMapper.insert(accountInfo);
        if (insert == 0) {
            return ResponseData.error("注册失败请联系管理员！");
        }
        QueryWrapper<ClientInfo> clientInfoQueryWrapper = new QueryWrapper<>();
        clientInfoQueryWrapper.eq("client_code", clientCode);
        ClientInfo clientInfo = clientInfoService.getBaseMapper().selectOne(clientInfoQueryWrapper);
        if (clientInfo == null) {
            this.removeById(accountInfo.getId());
            return ResponseData.error("客户端不存在！");
        }
        AccountClient accountClient = new AccountClient();
        accountClient.setUsername(accountInfo.getUsername());
        accountClient.setClientId(clientInfo.getId());
        accountClient.setPersistentLogin(clientInfo.getPersistentLogin());
        accountClient.setClientCode(clientCode);
        accountClient.setAccountId(accountInfo.getId());
        boolean saveClient = accountClientService.save(accountClient);
        if (!saveClient) {
            this.removeById(accountInfo.getId());
            return ResponseData.success("关联客户端失败！");
        }
        UserInfo userInfo = new UserInfo();
        userInfo.setAccountId(accountInfo.getId());
        userInfo.setUsername(accountInfo.getUsername());
        userInfo.setSix(3);
        userInfo.setNickname(accountInfo.getUsername());
        userInfoService.addUserInfo(userInfo);
        return ResponseData.success("注册成功！");
    }

    @Override
    public ResponseData disable(Long id) {
        Account account = new Account();
        account.setId(id);
        account.setIsEnabled(2);
        int disable = this.baseMapper.updateById(account);
        if (disable == 0) {
            return ResponseData.error("禁用失败！请联系管理员。");
        }
        return ResponseData.success("操作成功！");
    }

    @Override
    public ResponseData locking(Long id, Integer lockingType) {
        int lock;
        int lockedlag = 1;
        Account account = this.baseMapper.selectById(id);


        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.MINUTE, 30);
        if (account == null) {
            return ResponseData.error("未找到用户！请联系管理员。");
        }
        if (account.getErrors()==null){
            account.setErrors(0);
        }
        if (lockingType == 1) {
            lock = account.getErrors() + 1;
            if (lock >= 5) {
                lockedlag = 2;
            }
        } else {
            lock = 5;
            lockedlag = 2;
        }
        account.setUnlockTime(cal.getTime());
        account.setErrors(lock);
        account.setLockedlag(lockedlag);
        this.baseMapper.updateById(account);
        if (lockedlag == 2) {
            return ResponseData.error("账户已经锁定！请30分钟后再试。");
        }
            return ResponseData.error("用户名密码错误！还有 " + (5 - lock) + " 次机会！");
    }

    @Override
    public ResponseData unlock(Long id) {
        Account account = new Account();
        account.setId(id);
        account.setLockedlag(1);
        account.setErrors(0);
        int unlock = this.baseMapper.updateById(account);
        if (unlock == 0) {
            return ResponseData.error("解锁失败，请联系管理员！");
        }
        return ResponseData.success("解锁成功，请重新登录！");
    }

    @Override
    public ResponseData setExpirationTime(Long id, Date endTime) {
        Account account = this.baseMapper.selectById(id);
        if (account == null) {
            return ResponseData.error("用户不存在");
        }
        if (endTime.getTime() <= new Date().getTime()) {
            return ResponseData.error("结束时间不能小于当前时间！");
        }
        account.setExpiredTime(endTime);
        int expired = this.baseMapper.updateById(account);
        if (expired == 0) {
            return ResponseData.error("设置失败！");
        }
        return ResponseData.success("设置成功！");
    }

    @Override
    public ResponseData getAccountInfo() {
        AccountResponse accountResponse = new AccountResponse();
        Account accountInfo = SecurityUtil.getAccountInfo();
        BeanUtils.copyProperties(accountInfo,accountResponse);

        UserInfo userInfo = userInfoService.getUserInfo(accountInfo.getUsername());
        accountResponse.setUserInfo(userInfo);
        accountResponse.setPassword(null);

        List<Tree<Object>> allbindMenu = roleMenuInfoService.getAllbindMenu();
        accountResponse.setMenuInfo(allbindMenu);

        List<PlatformInfo> platformInfos = accountPlatformInfoService.selectAllPlatform();

        if (platformInfos!=null&&platformInfos.size() > 0) {
            List<PlatformInfo> platformInfo = platformInfos.stream().filter(itme -> itme.getBinding() != null && itme.getBinding() == 2).collect(Collectors.toList());
            accountResponse.setPlatforms(platformInfo);
        }

        return ResponseData.success(accountResponse);
    }
}

